
#pragma once
#include "InternalManager.h"
#include "CudaDeviceBuffer.h"
#include "CudaHostBuffer.h"
#include "CudaSource.h"
typedef unsigned char byte;

namespace GRIP
{
	namespace Cuda
	{
		/// <summary>
		/// CudaManager handles all of the CUDA and Direct3D initialization and interop.
		/// </summary>
		public ref class CudaManager abstract sealed
		{
		public:
			/// <summary>
			/// Prepares CUDA for handling GPU instructions and registers Direct3D with it.
			/// </summary>
			static void InitializeCuda();

			/// <summary>
			/// Uninitializes CUDA and Direct3D.
			/// </summary>
			static void Cleanup();
			
			/// <summary>
			/// Explicitly copies a managed array to a GPU buffer, without requiring a
			/// CudaHostBuffer to wrap the data first.
			/// </summary>
			/// <typeparam name="T">The type of the source array</typeparam>
			/// <param name="Source">The source array to be copied</param>
			/// <param name="Target">The target GPU array to copy to</param>
			generic<typename T>
			static void CopyBytesToDevice(array<T>^ Source, CudaDeviceBuffer^ Target);
			
			/// <summary>
			/// Explicitly copies a GPU buffer to a managed array, without requiring a
			/// CudaHostBuffer to wrap the data first.
			/// </summary>
			/// <typeparam name="T">The type of the Target array</typeparam>
			/// <param name="Source">The source GPU array to be copied</param>
			/// <param name="Target">The target host array to copy to</param>
			generic<typename T>
			static void CopyBytesFromDevice(CudaDeviceBuffer^ Source, array<T>^ Target);

			/// <summary>
			/// Copies a GPU buffer to a Direct3D Surface, so WPF can render it.
			/// </summary>
			/// <param name="Source">The source GPU buffer to be copied</param>
			/// <param name="Target">The CudaSource which holds the Direct3D Surface to copy to</param>
			static void RenderToMappedSource(CudaDeviceBuffer^ Source, CudaSource^ Target);

			/// <summary>
			/// Returns the ID of the CUDA device being used.
			/// </summary>
			/// <returns>ID of the CUDA device being used</returns>
			static int GetDevID();
		};
	}
}
